% ESTIMA_LOOP_PARALLEL 
% This loop has been written for Paralell Computation 


%% 1.Organize Output storage (Broadcast variables) 
logprior_mat(:,2)= -inf*ones(nstrvals,1);
loglikel_mat(:,2)= -inf*ones(nstrvals,1);
logpostd_mat(:,2)= -inf*ones(nstrvals,1);

parmodemat = zeros(numpar, nstrvals);


mat_exitflag     = nan(1, nstrvals);
mat_iterations   = nan(1, nstrvals); 
mat_time         = nan(1, nstrvals); 
%% 3. Start a cell that can save output as we go along
% TAB_LOOP
% =========================================================================
% tab_loop           =emptycell(numpar+7,nstrvals+1);
% tab_loop(1:numpar,1)=parnames;
% tab_loop(numpar+2:end,1)={'logPost';'logLikel';'Number';'Iteration count';'exitflag';'minutes'};
% cd(outpath);save tab_loop;cd(cucd);


%% 2. Assign default values to ESTIMOPT if they do not exist
% =========================================================================
if ~exist('estimopt', 'var'); estimopt = []; end;
[~,estimopt]   =ch_field(estimopt,'TolFun',1e-5);
[~,estimopt]   =ch_field(estimopt,'MaxFuneval',200000);
[~,estimopt]   =ch_field(estimopt,'MaxIter',400);
[junk,estimopt]=ch_field(estimopt,'Display','off');
estimopt       =setfield(estimopt,'UseParallel','on'); 

 
%% 3  Preliminary assigments and truncations before loop begins
%     Formerly known as INDMAT, this is the matrix of transformations
%     PARVECMODE is an empty vector with the calibrated values in
% =========================================================================
partrmat_est          =partrmat(parposest, :);
parestmat             =zeros(length(parposest),2); 
tic; 
%%    
parfor ii=1:nstrvals;
    parvecmode            =zeros(numpar, 1);
    parvecmode(parposcal) =parcalval;
    disp(['Starting Value',num2str(ii)]); 
    switch case_estima
        case 1
            [lpostmin,xestmode,mat_iterations(ii),mat_exitflag(ii),mat_time(ii)]=feval(@lmj_postoptim_csminwel,parstrvals(parposest,ii),partrmat_est,parvecmode,parposest,estimopt,funcmod,Y,trainvec,prpar,prss,solveopt,addsol,ssposest);
        case 2 
            [lpostmin,xestmode,mat_exitflag(ii),fminconout,mat_time(ii),mat_iterations(ii)]=feval(@estima_fmincon_central,parstrvals(parposest,ii),parvecmode,parposest,funcmod,Y,trainvec,prpar,prss,solveopt,addsol,ssposest,estimopt);
    end    
    % Assign output from runs 
   parvecmode(parposest)                  = xestmode; 
   parestmat(:,ii)                        = xestmode; 
   
   % PARMODEMAT     Matrix of output vectors
   parmodemat(:, ii) = parvecmode;
    
   [logpostd_mat(ii,2),loglikel_mat(ii,2)]=feval(@lmj_postmax,parestmat(:,ii),parvecmode,parposest,funcmod,Y,trainvec,prpar,prss,solveopt,addsol,ssposest);
   logprior_mat(ii,2)                    =logpostd_mat(ii,2)-loglikel_mat(ii,2);        
end
%%
try
    cd(outpath);
    save workspace;
    cd(cucd);
catch
    disp('Could not save workspace');
end

mat_exitflag     = nan(1, nstrvals);
mat_iterations   = nan(1, nstrvals); 
mat_time         = nan(1, nstrvals);

optimat    = [mat_iterations; mat_exitflag; mat_time/60];

CPUtime=sum(mat_time/60);     
runTime=toc/60;     
            
matlabpool close
    % =========================================================================
    % 8. OUTPUT
    % Output that must be produced by each code
    % -----------------------------------------
    % XESTMODE:  Estimated value
    % ESTIMITER: Number of Iterations
    % EXITFLAG : How routine ended
    % LPOSTMIN : Exit value of posterior (min)
    % =========================================================================
    
    
    
    %%
    % =================================================================
    % 8.3.
    % Write TAB_LOOP
    % ===================================================================
    
tab_loop=emptycell(numpar+7,nstrvals+1);
tab_loop(1:numpar,1)=parnames;
tab_loop(numpar+2:end,1)={'logPost';'logLikel';'Number';'Iteration count';'exitflag';'minutes'};
cd(outpath);save tab_loop;cd(cucd);

tab_loop(1:numpar,2:end)=num2cprec(parmodemat,15);
tab_loop(numpar+2,2:end)=num2cprec(logpostd_mat(:,2));
tab_loop(numpar+3,2:end)=num2cprec(loglikel_mat(:,2));
tab_loop(numpar+4,2:end)=num2cprec(1:nstrvals);
tab_loop(numpar+5,2:end)= num2cprec(mat_iterations); % Iteration count
tab_loop(numpar+6,2:end)= num2cprec(mat_exitflag); % Exit flag
tab_loop(numpar+7,2:end)= num2cprec(mat_time/60);
%     
% save output
cd(outpath) 
save mat_loop logprior_mat logpostd_mat parmodemat optimat loglikel_mat
  if ~isunix || size(tab_loop,2) < 200 
     xlswrite('tab_loop', tab_loop);
  else
     savecell(tab_loop,[],outpath,'tab_loop');
  end
cd(cucd)

dispaj('Total Running time=',runTime); 

